#ifndef FILESTREAM_H
#define FILESTREAM_H

#include <QObject>
#include <windows.h>
#include <setjmp.h>
#include <QStack>
#include <QTreeWidgetItem>

extern "C" {

enum {
    T_Print = 1,
    T_Read,
    T_Write
};

enum {
    LOG_Verbose = 1,
    LOG_Debug,
    LOG_Info,
    LOG_Warning,
    LOG_Error
};

typedef struct {
    int pos;
    int bit;
    int len; // Byte
    int size; // Bit
    unsigned char sign; // 默认TQ_UNSIGN
    unsigned char sort; // 默认TQ_LITTLE
    unsigned char *buf;
} InOutStreamType;

typedef struct {
    void (*FreeAllBuffer) (void);
    void (*ThrowError)(int errCode);
    void (*Log)(int type, const char *format, va_list arg);

    void (*PrintLevelAdd)(int type);
    void (*PrintLevelSub)(int type);
    void (*PrintLabelKey)(const char *key, int type);
    void (*PrintLabelValue)(const char *val, int type);
    void (*PrintLabelEndKey)(int type);
} StreamApi;

typedef void (*PauseAllFunc)(void *buf, int type);

}

struct TreeItem : public QTreeWidgetItem {
    int dataPos;
    int dataLen;
    int srcPos;
};

class FileStream : public QObject
{
    Q_OBJECT
public:
    explicit FileStream(const QString dllPath, QObject *parent = nullptr);
    ~FileStream();

    bool loadDllLibrary(const QString dllPath);
    void closeLibrary(void);

    void setData(QByteArray &data);
    bool runPauseDll(TreeItem *root);

    static QString getSupportFileFilter(const QString dllPath);

signals:
    void onError(int line);
    void onLog(int type, QString log);

private:
    static FileStream *m_this;
    InOutStreamType *m_inOut;
    void (*FreeAllBuffer) (void);
    PauseAllFunc m_pauseAll;

    static void ThrowError(int errCode);
    static void LogOut(int type, const char *format, va_list arg);
    static void PrintLevelAdd(int type);
    static void PrintLevelSub(int type);
    static void PrintLabelKey(const char *key, int type);
    static void PrintLabelValue(const char *val, int type);
    static void PrintLabelEndKey(int type);

private:
    HMODULE m_handle;
    jmp_buf m_abnormalEnv;
    QStack<TreeItem*> m_treeStrack;
    TreeItem *m_curTree;
    TreeItem *m_prtTree;
};

#endif // FILESTREAM_H
